﻿
namespace Logic
{
    public class GrossbergLayer : Layer
    {
        private float[][] _m;
        public bool WH { get; set; }

        public GrossbergLayer(int size, int prevLayerSize)
        {
            Neurons = new Neuron[size];
            _m = new float[size][];
            for (int i = 0; i < size; i++)
            {
                Neurons[i] = new Neuron(prevLayerSize);
                _m[i] = new float[prevLayerSize];
            }
        }

        public override string Symbol
        {
            get { return "GrossbergLayer"; }
        }

        public void Learn(float[] prevLayerSignals, float[] expectedOutput, float gamma, float momentum)
        {
            int winnerIndex = 0;
            for (int i = 0; i < prevLayerSignals.Length; i++)
            {
                if (prevLayerSignals[i] > 0)
                {
                    winnerIndex = i;
                    break;
                }
            }

            var ii = 0;
            foreach (var neuron in Neurons)
            {
                var oldWeight = neuron.Weights[winnerIndex];
                var activationDifferential = ActivationFunction.ComputeDerrivative(oldWeight);
                neuron.Evaluate(ActivationFunction, prevLayerSignals);
                var outputSignal = neuron.OutputSignal;
                var newWeight = (float)(oldWeight + gamma * (expectedOutput[ii] - outputSignal) * activationDifferential + momentum * _m[ii][winnerIndex]);
                _m[ii][winnerIndex] = newWeight - oldWeight;
                neuron.Weights[winnerIndex] = newWeight;
                for (var j = 0; j < _m[ii].Length; j++)
                    if (j != winnerIndex)
                        _m[ii][j] = 0;
                ii++;
            }
        }
    }
}
